package com.totem.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.totem.admin.mapper.TSubscribeDailyEndMapper;
import com.totem.admin.model.TSubscribeDailyEnd;
import com.totem.base.enums.HandleStateEnum;
import com.totem.base.enums.OrderTypeEnum;
import com.totem.base.enums.PaymentStateEnum;
import com.totem.base.enums.StateEnum;
import com.totem.order.mapper.TOrderMapper;
import com.totem.order.mapper.TSubscribeOrderItemMapper;
import com.totem.order.model.TOrders;
import com.totem.order.model.TSubscribeOrderItems;
import com.totem.order.service.ITSubscribeOrderItemService;
import com.totem.product.model.TSubscribe;
import com.totem.product.service.ITSubscribeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigInteger;
import java.time.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TSubscribeOrderItemServiceImpl extends ServiceImpl<TSubscribeOrderItemMapper, TSubscribeOrderItems> implements ITSubscribeOrderItemService {
    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private TSubscribeDailyEndMapper tSubscribeDailyEndMapper;


    @Override
    public boolean updateReturnHandleState(List<Long> customerIdList, String customerState, Map<String, TSubscribe> subscribeMap) {
        LocalDateTime now = LocalDateTime.now();
        // 当前客户的认购包收益改变,基金收益时会过滤已封号客户,不用处理
        LambdaQueryWrapper<TOrders> orderQuery = new LambdaQueryWrapper<>();
        orderQuery.in(TOrders::getCustomerId, customerIdList);
        orderQuery.eq(TOrders::getOrderType, OrderTypeEnum.SUBSCRIBE.getCode());
        orderQuery.eq(TOrders::getPaymentState, PaymentStateEnum.FINISHED.getCode());
        orderQuery.eq(TOrders::getState, StateEnum.NORMAL.getCode());
        List<TOrders> orderList = tOrderMapper.selectList(orderQuery);
        if(!CollectionUtils.isEmpty(orderList)){
            List<Long> orderIdList = orderList.stream().map(TOrders::getId).toList();
            LambdaQueryWrapper<TSubscribeOrderItems> orderItemQuery = new LambdaQueryWrapper<>();
            orderItemQuery.in(TSubscribeOrderItems::getOrderId, orderIdList);
            if(StateEnum.isNormal(customerState)) {
                orderItemQuery.eq(TSubscribeOrderItems::getReturnHandleState, HandleStateEnum.STOP.getCode());
            }else{
                orderItemQuery.eq(TSubscribeOrderItems::getReturnHandleState, HandleStateEnum.HANDLING.getCode());
            }
            List<TSubscribeOrderItems> itemList = baseMapper.selectList(orderItemQuery);
            Map<Long, TOrders> orderMap = orderList.stream().collect(Collectors.toMap(TOrders::getId, Function.identity()));
            Map<Long, Long> sdeCountMap = new HashMap<>();
            if(StateEnum.isNormal(customerState)){
                // 查询已结算天数
                QueryWrapper<TSubscribeDailyEnd> countDayend = new QueryWrapper<>();
                countDayend.select("order_id, count(*) as count")
                        .in("order_id", orderIdList)
                        .groupBy("order_id");
                List<Map<String, Object>> sdeCountList = tSubscribeDailyEndMapper.selectMaps(countDayend);

                sdeCountList.forEach(map->{
                    Object orderIdObj = map.get("order_id");
                    Object countObj = map.get("count");
                    sdeCountMap.put(((BigInteger)orderIdObj).longValue(), (Long)countObj);
                });
            }
            List<TSubscribeOrderItems> updateItemList = itemList.stream().map(item->{
                Long orderId = item.getOrderId();
                String subscribeName = item.getSubscribeName();
                TSubscribeOrderItems updateItem = TSubscribeOrderItems.builder()
                        .id(item.getId())
                        .build();
                if(StateEnum.isNormal(customerState)) {
                    updateItem.setReturnHandleState(HandleStateEnum.HANDLING.getCode());
                    // 延长结束时间
                    // 已结算天数
                    Long count = sdeCountMap.get(orderId);
                    count=count==null?0:count;
                    TOrders order = orderMap.get(orderId);
                    TSubscribe tSubscribe = subscribeMap.get(subscribeName);
                    Integer subscribeDays = tSubscribe.getSubscribeDays();
                    // 结算天数为0,即当天就恢复封号状态,不需要延长结束时间
                    if(count>0 && order!=null){
                        // 暂停的时间,即需要延长的时间
                        long days = subscribeDays-count;
                        // 新的结束时间
                        Date newCloseTime = null;
                        // 结算天数已达到周期,即已结束,不需要延长结束时间
                        if(days>0){
                            Date oldCloseTime = item.getCloseTime();
                            LocalDateTime oldCloseDateTime = LocalDateTimeUtil.of(oldCloseTime);
                            LocalTime oldTime = oldCloseDateTime.toLocalTime();
                            LocalDateTime newCloseDateTime = null;
                            // 延长的基准时间以更靠后的时间为准
                            if(now.isBefore(oldCloseDateTime)){
                                newCloseDateTime = oldCloseDateTime.plusDays(days);
                            }else{
                                newCloseDateTime = now.plusDays(days);
                            }
                            LocalDate newCloseDate = newCloseDateTime.toLocalDate();
                            newCloseDateTime = newCloseDate.atTime(oldTime);
                            newCloseTime = Date.from(newCloseDateTime.atZone(ZoneId.systemDefault()).toInstant());
                            updateItem.setCloseTime(newCloseTime);
                        }
                    }
                }else{
                    updateItem.setReturnHandleState(HandleStateEnum.STOP.getCode());
                }
                return updateItem;
            }).toList();
            List<TSubscribeOrderItems> updateItemListFiltered = updateItemList.stream()
                    .filter(item->item.getCloseTime()!=null || StringUtils.isNotBlank(item.getReturnHandleState()))
                    .collect(Collectors.toList());
            super.updateBatchById(updateItemListFiltered);
        }
        return true;
    }
}
